package com.cyj.comment.listener;

import com.cyj.comment.entity.VoucherOrder;
import com.cyj.comment.service.VoucherOrderService;
import com.cyj.comment.service.impl.VoucherOrderServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName VoucherOrderListener
 * @Description TODO
 * @Author chixiaowai
 * @Date 2023/6/13 18:42
 * @Version 1.0
 */

@Slf4j
@Component
@RabbitListener(queues = "order_queue")
public class VoucherOrderListener implements ChannelAwareMessageListener {

    @Autowired
    private VoucherOrderService voucherOrderService;

    //线程池
    private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newSingleThreadExecutor();

    @RabbitHandler(isDefault=true)
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {

        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        try {
            //1.接收转换消息
            ObjectMapper mapper = new ObjectMapper();
            VoucherOrder voucherOrder = mapper.readValue(message.getBody(), VoucherOrder.class);
            //2. 处理业务逻辑
            try {
                // 2.创建订单
                SECKILL_ORDER_EXECUTOR.submit(
                        () -> voucherOrderService.handleVoucherOrder(voucherOrder));

                log.info("订单已执行");
            } catch (Exception e) {
                log.error("处理订单异常", e);
            }
            //3. 手动签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e) {

            //4.拒绝签收
            /*
            第三个参数：requeue：重回队列。如果设置为true，则消息重新回到queue，broker会重新发送该消息给消费端
             */
            channel.basicNack(deliveryTag,true,true);

        }
    }
}

